﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Common.Cryptography
{
    public static class RijndaelHelper
    {

        #region Global Var(s)

        private static Rijndael RijndaelEninge = null;
        private const int RijndaelKeySize = 32;
        private const int RijndaelIVSize = 16;

        #endregion

        #region Basic

        public static void init(string strPassword)
        {
            if (String.IsNullOrEmpty(strPassword))
                throw new ArgumentNullException("strPassword");

            RijndaelEninge = Rijndael.Create();
            RijndaelEninge.Key = CryptographyHelper.GetKeyFromPassword(strPassword, RijndaelKeySize);
            RijndaelEninge.IV = CryptographyHelper.GetKeyFromPassword(strPassword, RijndaelIVSize);
        }

        public static void free()
        {
            if (RijndaelEninge.isNull() == false)
                RijndaelEninge.Clear();
        }

        #endregion

        #region Encryption

        public static byte[] Encrypt(byte[] RawData)
        {
            if (RijndaelEninge.isNull())
                throw new ArgumentNullException("Must call init frist!");
            if (RawData.isNull() || RawData.Length < 1)
                throw new ArgumentNullException("RawData");

            MemoryStream ms = null;
            CryptoStream cs = null;
            BinaryWriter bw = null;

            try
            {
                ICryptoTransform ct = RijndaelEninge.CreateEncryptor(RijndaelEninge.Key, RijndaelEninge.IV);
                ms = new MemoryStream();
                cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
                bw = new BinaryWriter(cs);

                bw.Write(RawData);
            }
            finally
            {
                if (bw.isNull() == false)
                    bw.Close();
                if (cs.isNull() == false)
                    cs.Close();
                if (ms.isNull() == false)
                    ms.Close();
            }

            return ms.ToArray();
        }


        #endregion

        #region Decryption

        public static byte[] Decrypt(byte[] RawData)
        {
            if (RijndaelEninge.isNull())
                throw new ArgumentNullException("Must call init frist!");
            if (RawData.isNull() || RawData.Length < 1)
                throw new ArgumentNullException("RawData");

            MemoryStream ms = null;
            CryptoStream cs = null;
            BinaryReader br = null;
            byte[] dptData = null;

            try
            {
                ICryptoTransform ct = RijndaelEninge.CreateDecryptor(RijndaelEninge.Key, RijndaelEninge.IV);
                ms = new MemoryStream(RawData);
                cs = new CryptoStream(ms, ct, CryptoStreamMode.Read);
                br = new BinaryReader(cs);

                dptData = br.ReadBytes(RawData.Length);
            }
            finally
            {
                if (br.isNull() == false)
                    br.Close();
                if (cs.isNull() == false)
                    cs.Close();
                if (ms.isNull() == false)
                    ms.Close();
            }

            return dptData;
        }


        #endregion
    }
}
